#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_mac.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"

#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

#include "mbedtls/md5.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "my_wss.h"
#include "cJSON.h"
#include "led.h"
#include "get_time.h"
#include "my_uart.h"

#define CONFIG_XLINK_DEVICE_ID 12345

// 在全局作用域下创建结构体变量
int Create_Change = 0;
int Create_Timed = 0;
int Subscribe_End = 0; // 订阅完成标志位
int interval = 0;      // 定时上报任务的间隔时间
int inaccuracie = 0;   // 误差值
static uint8_t g_esp_mac[6] = {0};
char mac_str[13] = {0}; // mac地址
char g_publish_topic[100] = "";
char subscribe_topic[100] = "";
char json_append[20] = {0};
myCJson cjson_data;
N2O_change_Task_Params N2O_change;
N2O_timed_Task_Params N2O_timed;
esp_mqtt_client_handle_t my_client;
TaskHandle_t N2OAlarmHandle;
TaskHandle_t N2OChangeHandle;
TaskHandle_t N2OTimedHandle;
static const char *TAG = "MQTTWSS_EXAMPLE";

#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1
static const uint8_t mqtt_eclipseprojects_io_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
#else
extern const uint8_t mqtt_eclipseprojects_io_pem_start[] asm("_binary_mqtt_eclipseprojects_io_pem_start");
#endif
extern const uint8_t mqtt_eclipseprojects_io_pem_end[] asm("_binary_mqtt_eclipseprojects_io_pem_end");

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event);

/**
 * @description: 构建一个订阅主题
 * @param {char} *paket_data
 * @return {*}	ESP_LOGI(TAG, "client subscribe:%s", paket_data);
 */
void packet_subscribe_topic(char *paket_data)
{
    esp_read_mac(g_esp_mac, ESP_MAC_WIFI_STA); // 读取mac地址
    sprintf(mac_str, "%02x%02x%02x%02x%02x%02x", g_esp_mac[0], g_esp_mac[1], g_esp_mac[2], g_esp_mac[3], g_esp_mac[4], g_esp_mac[5]);
    ESP_LOGI(TAG, "mac trans:%s", mac_str); // 将mac转换成字符串
    char topic_client[] = "ALIVE/CLIENT/";
    char topic_gateway[] = "GateWayBle/";
    char topic_multi_layer_wildcard[] = "/#";

    strcat(paket_data, topic_client);
    strcat(paket_data, topic_gateway);
    strcat(paket_data, mac_str);
    strcat(paket_data, topic_multi_layer_wildcard);

    ESP_LOGI(TAG, "client subscribe:%s", paket_data);
}

/**
 * @description: 构建一个发布主题
 * @param {char} *paket_data
 * @return {*}	ESP_LOGI(TAG, "client subscribe:%s", paket_data);
 */
void packet_publish_topic(char *paket_data)
{
    char xlink_client_id[14] = {0};
    esp_read_mac(g_esp_mac, ESP_MAC_WIFI_STA); // 读取mac地址
    sprintf(mac_str, "%02x%02x%02x%02x%02x%02x", g_esp_mac[0], g_esp_mac[1], g_esp_mac[2], g_esp_mac[3], g_esp_mac[4], g_esp_mac[5]);
    ESP_LOGI(TAG, "mac trans:%s", mac_str); // 将mac转换成字符串

    char topic_client[] = "ALIVE/SERVER/";
    char topic_gateway[] = "GateWayBle/";
    sprintf(xlink_client_id, "%d", CONFIG_XLINK_DEVICE_ID);
    strcat(paket_data, topic_client);
    strcat(paket_data, topic_gateway);
    strcat(paket_data, mac_str);
    strcat(paket_data, "/");
    strcat(paket_data, xlink_client_id);

    // strcat(paket_data, topic_multi_layer_wildcard);

    ESP_LOGI(TAG, "client publish:%s", paket_data);
}

void mqtt_app_start(void)
{
    // ESP_LOGI(TAG, "[APP] Startup..");
    // ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    // ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);

    esp_mqtt_client_config_t mqtt_cfg = {
        .session.disable_clean_session = true, // 设置为 true，以清除之前的会话数据
        .broker.address.uri = "wss://mesh.szalive.com:8084/mqtt",
        .credentials = {
            .username = "alive",                      // 用户名
            .client_id = "alive_32",                  // 客户端ID
            .authentication.password = "alivegogogo", // 密码
        },
        .broker.verification.certificate = (const char *)mqtt_eclipseprojects_io_pem_start, /*证书数据*/
    };

    ESP_LOGI(TAG, "[APP] Free memory: %lu bytes", (unsigned long)esp_get_free_heap_size()); // 获取可用堆的大小。
    // 初始化mqtt，返回值为客户端句柄
    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    // 注册 MQTT事件
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    // 启动MQTT
    esp_mqtt_client_start(client);
}

/*传给 esp_mqtt_client_register_event 的参数可作为 handler_args 访问*/
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRId32 "", base, event_id);
    mqtt_event_handler_cb(event_data);
}
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    my_client = client;
    int msg_id;
    switch (event->event_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        packet_publish_topic(g_publish_topic);
        packet_subscribe_topic(subscribe_topic);
        // esp_mqtt_client_unsubscribe(client, "ALIVE/CLIENT/GateWayBle/30c6f7f7a4d8");
        // esp_mqtt_client_unsubscribe(client, "ALIVE/SERVER/GateWayBle/30c6f7f7a4d8/12345");
        msg_id = esp_mqtt_client_subscribe(client, subscribe_topic, 0);
        // msg_id = esp_mqtt_client_subscribe(client, "ALIVE/CLIENT/GateWayBle/30c6f7f7a4d8", 0);
        // msg_id = esp_mqtt_client_subscribe(client, "ALIVE/SERVER/GateWayBle/30c6f7f7a4d8/12345", 0);
        Subscribe_End = 1;
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        // msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
        // ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
        ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        // 发布首次连接消息
        if (Subscribe_End == 1)
        {
            Subscribe_End = 0;
            Publish_First_Connet(client);
        }
        //  msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "hhhhhhh", 0, 0, 0);
        // ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("nowDATA=%.*s\r\n", event->data_len, event->data);

        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        unsigned char *json_buffer = malloc(event->data_len);
        if (json_buffer != NULL)
        {
            ESP_LOGI(TAG, "json_buffer != NULL");
            ESP_LOGI(TAG, "data_len = %d", event->data_len);
            // 将json数据存入json_buffer
            memcpy(json_buffer, event->data, event->data_len);
            const char *char_buffer = (const char *)json_buffer;
            // 解析json数据
            cJSON *root = cJSON_Parse(char_buffer);
            if (cJSON_GetObjectItem(root, "append") != NULL)
            {
                cJSON *append_item = cJSON_GetObjectItem(root, "append");
                strncpy(json_append, append_item->valuestring, sizeof(json_append) - 1);
                json_append[sizeof(json_append) - 1] = '\0'; // 确保字符串以 null 结尾
            }
            // 获取要比对的数据，存入结构体 cjson_data
            int ret = get_first_jsondata(root, &cjson_data); // 如果命令是上报首次连接
            if (ret)
            {
                ret = 0;
                Get_system_time(&system_timestamp, &cjson_data);
                print_system_time();
                N2O_Alarm_TaskKEY();
                N2O_SyncPolicy_TaskKey();
            }
            ret = Read_N2O_jsondata(root, &cjson_data); // 如果命令是读取N2O浓度
            if (ret)
            {
                printf("jiexi_Read_N2O_jsondata_chegngong\n");
                ret = 0;
                if (strcmp(cjson_data.operate, "query") == 0 && strcmp(cjson_data.sub_operate, "read") == 0)
                {
                    printf("开始发布\n");
                    // 发布N2O传感器读数到主题
                    Publish_N2O_concentration(client);
                }
                else if (strcmp(cjson_data.operate, "report") != 0 && (strcmp(cjson_data.sub_operate, "close") != 0 && strcmp(cjson_data.sub_operate, "open") != 0))
                {

                    Publish_Reply_Message(client, false, "error");
                }
            }
            ret = Read_N2OControl_jsondata(root, &cjson_data);
            if (ret)
            {
                printf("jiexi_Read_N2OControl_jsondata_chegngong\n");
                ret = 0;
                if (strcmp(cjson_data.mode, "changereport") == 0)
                {
                    if (strcmp(cjson_data.sub_operate, "open") == 0)
                    {
                        sscanf(cjson_data.inaccuracie, "%d", &N2O_change.inaccuracie);
                        printf("N2O_Change_task start\n");
                        if (Create_Change == 0)
                        {
                            Create_Change = 1;
                            // 创建状态改变上报任务
                            N2O_change.client = client;
                            inaccuracie = N2O_change.inaccuracie;
                            xTaskCreate(N2O_Change_task, "N2O_Change_task", 4096, &N2O_change, 10, &N2OChangeHandle);
                        }
                        else if (Create_Change == 1 && inaccuracie != N2O_change.inaccuracie)
                        {
                            vTaskDelete(N2OChangeHandle);
                            printf("there\n");
                            inaccuracie = N2O_change.inaccuracie;
                            xTaskCreate(N2O_Change_task, "N2O_Change_task", 4096, &N2O_change, 10, &N2OChangeHandle);
                        }
                        else if (Create_Change == 1 && inaccuracie == N2O_change.inaccuracie)
                        {
                            //  任务已创建，恢复任务
                            vTaskResume(N2OChangeHandle);
                        }
                    }
                    else if (strcmp(cjson_data.sub_operate, "close") == 0)
                    {
                        printf("close N2O_Change_task\n");
                        // 挂起状态改变上报任务
                        vTaskSuspend(N2OChangeHandle);
                    }
                }

                if (strcmp(cjson_data.mode, "Timedreport") == 0)
                {
                    int interval_time = safe_atoi(cjson_data.interval);
                    printf("interval_time = %d\n", interval_time);
                    if ((interval_time < 1000) && (strcmp(cjson_data.sub_operate, "open") == 0))
                    {
                        Publish_Reply_Message(client, false, "interval");
                    }
                    else
                    {
                        if (strcmp(cjson_data.sub_operate, "open") == 0)
                        {
                            // Publish_Reply_Message(client, true);
                            //  创建定时上报任务
                            printf("N2O_Timed_task start\n");
                            sscanf(cjson_data.interval, "%d", &N2O_timed.interval);
                            printf("\ncjson_data.interval = %s,N2O_timed.interval = %d,interval = %d\n", cjson_data.interval, N2O_timed.interval, interval);
                            if (Create_Timed == 0)
                            {
                                printf("there1\n");
                                Create_Timed = 1;
                                N2O_timed.client = client;
                                // sscanf(cjson_data.interval, "%d", &N2O_timed.interval);
                                interval = N2O_timed.interval;
                                xTaskCreate(N2O_Timed_task, "N2O_Timed_task", 4096, &N2O_timed, 9, &N2OTimedHandle);
                                Publish_Reply_Message(client, true, "open");
                            }
                            else if (Create_Timed == 1 && interval != N2O_timed.interval)
                            {
                                vTaskDelete(N2OTimedHandle);
                                printf("there2\n");
                                // sscanf(cjson_data.interval, "%d", &N2O_timed.interval);
                                interval = N2O_timed.interval;
                                xTaskCreate(N2O_Timed_task, "N2O_Timed_task", 4096, &N2O_timed, 9, &N2OTimedHandle);
                                Publish_Reply_Message(client, true, "open");
                            }
                            else if (Create_Timed == 1 && interval == N2O_timed.interval)
                            {
                                printf("there3\n");
                                //  任务已创建，恢复任务
                                vTaskResume(N2OTimedHandle);
                                Publish_Reply_Message(client, true, "open");
                            }
                        }
                        else if (strcmp(cjson_data.sub_operate, "close") == 0)
                        {
                            //  删除定时上报任务
                            printf("N2O_Timed_task close\n");
                            vTaskSuspend(N2OTimedHandle);
                            Publish_Reply_Message(client, true, "close");
                        }
                    }
                }
            }
            ret = N2OPolicy_jsondata(root, &cjson_data);
            if (ret)
            {
                printf("jiexi_Read_N2OPolicy_jsondata_chegngong\n");
                ret = 0;
                Run_N2OPolicy_JsonData(client);
            }
            ret = N2OAlarm_jsondata(root, &cjson_data);
            if (ret)
            {
                printf("jiexi_Read_N2OAlarm_jsondata_chegngong\n");
                ret = 0;
                Run_N2OAlarm_JsonData(client);
            }

            // if (strcmp(cjson_data.sub_operate, "close") == 0 || strcmp(cjson_data.sub_operate, "open") == 0)
            // {
            //     Publish_Reply_Message(client, true, cjson_data.sub_operate);
            // }
            // else if ((strcmp(cjson_data.sub_operate, "close") != 0 && strcmp(cjson_data.sub_operate, "open") != 0) && strcmp(cjson_data.operate, "report") != 0)
            // {
            //     Publish_Reply_Message(client, false, "close");
            // }
            // else
            // {
            //     Publish_Reply_Message(client, false, 0);
            // }
            cJSON_Delete(root); // 删除json报文对象
        }
        free(json_buffer); // 释放申请的空间

        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%" PRIu32 "", (uint32_t)event->event_id);
        break;
    }
    return ESP_OK;
}
// 发布消息回复
void Publish_Reply_Message(esp_mqtt_client_handle_t *client, bool state, char *operate)
{
    cJSON *attributes = cJSON_CreateObject();
    cJSON *content;
    cJSON_AddStringToObject(attributes, "deviceType", "GateWay");
    cJSON_AddStringToObject(attributes, "subType", "GateWayBle");
    cJSON_AddStringToObject(attributes, "deviceMAC", "8c4b1416d2f0");
    cJSON_AddStringToObject(attributes, "familyId", "0");
    cJSON_AddStringToObject(attributes, "groupId", "0");
    cJSON_AddStringToObject(attributes, "operate", "reply");
    // content对象
    cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
    if (state == true)
    {
        cJSON_AddStringToObject(content, "msg", "success");
        cJSON_AddStringToObject(content, "code", "0");
    }
    else
    {
        cJSON_AddStringToObject(content, "msg", "failed");
        cJSON_AddStringToObject(content, "code", "1");
    }
    cJSON_AddStringToObject(content, "operate", operate);
    char source[] = "Alive";
    cJSON_AddStringToObject(attributes, "source", source);
    cJSON_AddStringToObject(attributes, "version", "v0.1");
    cJSON_AddStringToObject(attributes, "timestamp", "1647246643135");
    cJSON_AddStringToObject(attributes, "sign", "986fd8465e805b91f267d8af09f40ae2");
    cJSON_AddStringToObject(attributes, "append", cjson_data.append);
    // 发布
    char *ptr = cJSON_Print(attributes);
    int msg_id = esp_mqtt_client_publish(client, g_publish_topic, ptr, 0, 0, 0);
    if (ptr != NULL)
    {
        cJSON_free(ptr);
        ptr = NULL;
    }
    cJSON_Delete(attributes);
}

// 发布首次连接
void Publish_First_Connet(esp_mqtt_client_handle_t *client)
{
    cJSON *attributes = cJSON_CreateObject();
    cJSON *content;
    cJSON *sub_content;
    cJSON_AddStringToObject(attributes, "deviceType", "GateWay");
    cJSON_AddStringToObject(attributes, "subType", "GateWayBle");
    cJSON_AddStringToObject(attributes, "deviceMAC", "8c4b1416d2f0");
    cJSON_AddStringToObject(attributes, "familyId", "0");
    cJSON_AddStringToObject(attributes, "groupId", "0");
    cJSON_AddStringToObject(attributes, "operate", "report");
    // content对象
    cJSON_AddItemToObject(attributes, "content", content = cJSON_CreateObject());
    cJSON_AddStringToObject(content, "type", "virgin");
    // 内部content
    cJSON_AddItemToObject(content, "content", sub_content = cJSON_CreateArray());
    cJSON *item_tmp = cJSON_CreateObject();
    cJSON_AddStringToObject(item_tmp, "PROJECT_VER", "BLEGWV1_0_14");
    cJSON_AddStringToObject(item_tmp, "mqttSubjectPlan", "wss://mesh.szalive.com:8084/mqtt");
    cJSON_AddStringToObject(item_tmp, "used_entries", "167");
    cJSON_AddStringToObject(item_tmp, "free_entries", "28057");
    cJSON_AddStringToObject(item_tmp, "total_entries", "28224");
    cJSON_AddItemToArray(sub_content, item_tmp);
    char source[] = "Alive";
    cJSON_AddStringToObject(attributes, "source", source);
    cJSON_AddStringToObject(attributes, "version", "v0.1");
    cJSON_AddStringToObject(attributes, "timestamp", "1647246643135");
    cJSON_AddStringToObject(attributes, "sign", "986fd8465e805b91f267d8af09f40ae2");
    cJSON_AddStringToObject(attributes, "append", cjson_data.append);
    // 发布
    char *ptr = cJSON_Print(attributes);
    int msg_id = esp_mqtt_client_publish(client, g_publish_topic, ptr, 0, 0, 0);
    if (ptr != NULL)
    {
        cJSON_free(ptr);
        ptr = NULL;
    }
    cJSON_Delete(attributes);
}
// 上报首次连接回复报文解析
int get_first_jsondata(cJSON *rx_json, myCJson *data)
{
    static const char *TAG = "First jsondata";

    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    // ESP_LOGI(TAG, "%s", cJSON_Print(rx_json));

    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceType Item!");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no subType Item!");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceMAC Item!");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no groupId Item!");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no familyId Item!");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    cJSON *sub_content = cJSON_GetObjectItem(rx_json, "content");
    int sub_content_obj_size = cJSON_GetArraySize(sub_content); // 获取第二层"content "的项目数
    ESP_LOGI(TAG, "ARRAY SIZE:%d", sub_content_obj_size);

    if (cJSON_GetObjectItem(sub_content, "msg") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no msg Item!");

        return 0;
    }
    data->msg = cJSON_GetObjectItem(sub_content, "msg")->valuestring;

    if (cJSON_GetObjectItem(sub_content, "code") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no code Item!");

        return 0;
    }
    data->code = cJSON_GetObjectItem(sub_content, "code")->valuestring;

    if (cJSON_GetObjectItem(sub_content, "timeStr") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no timeStr Item!");

        return 0;
    }
    data->timeStr = cJSON_GetObjectItem(sub_content, "timeStr")->valuestring;

    if (cJSON_GetObjectItem(sub_content, "timestamp") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no timestamp Item!");

        return 0;
    }
    data->sub_timestamp = cJSON_GetObjectItem(sub_content, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no source Item!");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no version Item!");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no timestamp Item!");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no sign Item!");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no append Item!");

        return 0;
    }
    data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;
    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!");
    }
    return 0;
}

// 读取传感器读数报文解析
int Read_N2O_jsondata(cJSON *rx_json, myCJson *data)
{
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    static const char *TAG = "First jsondata";
    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    // ESP_LOGI(TAG, "%s", cJSON_Print(rx_json));

    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceType Item!");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no subType Item!");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceMAC Item!");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no groupId Item!");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no familyId Item!");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "content") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    cJSON *content = cJSON_GetObjectItem(rx_json, "content");

    if (cJSON_GetObjectItem(content, "type") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->type = cJSON_GetObjectItem(content, "type")->valuestring;

    cJSON *sub_content = cJSON_GetObjectItem(content, "content");
    if (cJSON_IsArray(sub_content))
    {
        cJSON *item = cJSON_GetArrayItem(sub_content, 0);
        int array_number = cJSON_GetArraySize(item);
        if (array_number == 0)
        {
            return 0;
        }

        if (cJSON_GetObjectItem(item, "operate") == NULL)
        {
            ESP_LOGE(TAG, "rx json have no operate Item!");

            return 0;
        }
        data->sub_operate = cJSON_GetObjectItem(item, "operate")->valuestring;
    }

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no source Item!");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no version Item!");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no timestamp Item!");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no sign Item!");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;
    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no append Item!");

        return 0;
    }
    data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;

    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!");
    }
    return 0;
}

// 控制传感器报文解析
int Read_N2OControl_jsondata(cJSON *rx_json, myCJson *data)
{
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    static const char *TAG = "Control_N2O_jsondata";
    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    // ESP_LOGI(TAG, "%s", cJSON_Print(rx_json));

    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceType Item!");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no subType Item!");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceMAC Item!");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no groupId Item!");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no familyId Item!");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "content") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    cJSON *content = cJSON_GetObjectItem(rx_json, "content");

    if (cJSON_GetObjectItem(content, "type") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->type = cJSON_GetObjectItem(content, "type")->valuestring;

    cJSON *sub_content = cJSON_GetObjectItem(content, "content");

    cJSON *item = cJSON_GetArrayItem(sub_content, 0);

    if (cJSON_GetObjectItem(item, "mode") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no mode Item!");

        return 0;
    }
    data->mode = cJSON_GetObjectItem(item, "mode")->valuestring;

    if (cJSON_GetObjectItem(item, "operate") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->sub_operate = cJSON_GetObjectItem(item, "operate")->valuestring;

    if (cJSON_GetObjectItem(item, "inaccuracie") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no inaccuracie Item!");
    }
    else
    {
        data->inaccuracie = cJSON_GetObjectItem(item, "inaccuracie")->valuestring;
    }

    if (cJSON_GetObjectItem(item, "interval") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no interval Item!");
    }
    else
    {
        data->interval = cJSON_GetObjectItem(item, "interval")->valuestring;
    }

    if (cJSON_GetObjectItem(item, "interval") == NULL && cJSON_GetObjectItem(item, "inaccuracie") == NULL)
    {
        ESP_LOGE(TAG, "rx json error");
        return 0;
    }

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no source Item!");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no version Item!");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no timestamp Item!");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no sign Item!");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;
    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no append Item!");

        return 0;
    }
    data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;

    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!");
    }
    return 0;
}

// 策略与策略开关报文解析
int N2OPolicy_jsondata(cJSON *rx_json, myCJson *data)
{
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    static const char *TAG = "Control_N2O_jsondata";
    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    // ESP_LOGI(TAG, "%s", cJSON_Print(rx_json));

    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceType Item!");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no subType Item!");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceMAC Item!");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no groupId Item!");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no familyId Item!");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "content") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    cJSON *content = cJSON_GetObjectItem(rx_json, "content");

    if (cJSON_GetObjectItem(content, "type") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->type = cJSON_GetObjectItem(content, "type")->valuestring;
    cJSON *sub_content = cJSON_GetObjectItem(content, "content");
    cJSON *item = cJSON_GetArrayItem(sub_content, 0);
    // 若命令是同步策略
    if (strcmp(data->type, "syncPolicy") == 0)
    {
        // 下面是策略的参数
        if (cJSON_GetObjectItem(item, "condition") == NULL)
        {
            printf("rx json have no condition!\n");
            return 0;
        }
        else
        {
            cJSON *sub_condition = cJSON_GetObjectItem(item, "condition");
            cJSON *time = cJSON_GetObjectItem(sub_condition, "time");
            cJSON *time_item = cJSON_GetArrayItem(time, 0);
            cJSON *device = cJSON_GetObjectItem(sub_condition, "device");
            cJSON *device_item = cJSON_GetArrayItem(device, 0);
            // time
            if (cJSON_GetObjectItem(time_item, "type") == NULL)
            {
                printf("rx json have no time_type!\n");
                return 0;
            }
            else
            {
                data->sub_type = cJSON_GetObjectItem(time_item, "type")->valuestring;
            }
            if (cJSON_GetObjectItem(time_item, "date") == NULL)
            {
                printf("rx json have no time_data!\n");
            }
            else
            {
                data->sub_date = cJSON_GetObjectItem(time_item, "date")->valuestring;
            }
            if (cJSON_GetObjectItem(time_item, "time") == NULL)
            {
                printf("rx json have no time_time!\n");
                return 0;
            }
            else
            {
                data->sub_time = cJSON_GetObjectItem(time_item, "time")->valuestring;
            }
            if (cJSON_GetObjectItem(time_item, "week") == NULL)
            {
                printf("rx json have no time_week!\n");
            }
            else
            {
                data->sub_week = cJSON_GetObjectItem(time_item, "week")->valuestring;
            }
            // device
            if (cJSON_GetObjectItem(device_item, "deviceType") == NULL)
            {
                printf("rx json have no device_deviceType!\n");
                return 0;
            }
            else
            {
                data->sub_deviceType = cJSON_GetObjectItem(device_item, "deviceType")->valuestring;
            }
            if (cJSON_GetObjectItem(device_item, "deviceId") == NULL)
            {
                printf("rx json have no device_deviceId!\n");
                return 0;
            }
            else
            {
                data->sub_deviceId = cJSON_GetObjectItem(device_item, "deviceId")->valuestring;
            }
        }
    }
    // 若命令是同步策略开关
    else if (strcmp(data->type, "syncPolicyEn") == 0)
    {
        if (cJSON_GetObjectItem(item, "policyEn") == NULL)
        {
            printf("rx json have no policyEn!\n");
            return 0;
        }
        else
        {
            data->sub_policyEn = cJSON_GetObjectItem(item, "policyEn")->valuestring;
        }

        if (cJSON_GetObjectItem(item, "policyType") == NULL)
        {
            printf("rx json have no policyEnType!\n");
            return 0;
        }
        else
        {
            data->sub_policyEnType = cJSON_GetObjectItem(item, "policyType")->valuestring;
        }
    }
    else
    {
        return 0;
    }

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        printf("rx json have no source Item!\n");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        printf("rx json have no version Item!\n");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        printf("rx json have no timestamp Item!\n");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        printf("rx json have no sign Item!\n");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        printf("rx json have no sign Item!\n");
        data->append = "0\0";
    }
    else
    {
        data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;
    }

    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!\n");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!\n");
    }
    return 0;
}

// 当第一次获得时间戳时设置系统时间
void Get_system_time(uint64_t *timestamp, myCJson *data)
{

    uint64_t cjson_timestamp = strtoull(data->sub_timestamp, NULL, 10); // strtoull函数是一个用于将字符串转换为uint64_t(unsigned long long)类型的整数的标准库函数这里的10指的是十进制
    printf("cjson_timestamp = %lld\n", cjson_timestamp);
    if (*timestamp == 0 && cjson_timestamp != 0)
    {
        *timestamp = cjson_timestamp;
        // *timestamp = 1685496726073;
        set_system_time(*timestamp);
    }
}

int safe_atoi(const char *str)
{
    if (str != NULL && str[0] != '\0')
    { // 确保字符串不是NULL且不为空
        return atoi(str);
    }
    else
    {
        // 适当的错误处理: 返回0或错误代码，或记录错误
        return 0; // 或者选择一个适当的默认值
    }
}

void Run_N2OPolicy_JsonData(esp_mqtt_client_handle_t *client)
{
    if (strcmp(cjson_data.type, "syncPolicyEn") == 0) // 判断是策略开关
    {
        if ((strcmp(cjson_data.sub_policyEn, "enable") == 0 || strcmp(cjson_data.sub_policyEn, "disable") == 0) &&
            (strcmp(cjson_data.sub_policyEnType, "onetime") == 0 || strcmp(cjson_data.sub_policyEnType, "onetimeWeek") == 0))
        {
            printf("syncPolicyEn cmd !!!\n");
            printf("policyEn:%s\n", cjson_data.sub_policyEn);
            printf("policyEnType:%s\n", cjson_data.sub_policyEnType);
            // 存储策略开关状态
            nvs_handle_t my_handle;
            esp_err_t err = nvs_open(N2O_Storage, NVS_READWRITE, &my_handle);
            err = nvs_set_str(my_handle, "policyEn", cjson_data.sub_policyEn);
            err = nvs_set_str(my_handle, "policyEnType", cjson_data.sub_policyEnType);
            err = nvs_commit(my_handle);
            nvs_close(my_handle);
            // 同步策略任务开启或关闭
            int check = N2O_SyncPolicy_TaskKey();
            if (check == 1)
            {
                Publish_Reply_Message(client, true, "syncPolicy");
            }
            else
            {
                Publish_Reply_Message(client, false, "syncPolicy");
            }
        }
    }
    if (strcmp(cjson_data.type, "syncPolicy") == 0) // 判断是同步策略
    {
        ESP_LOGI(TAG, "It is syncPolicy cmd!!!");
        int err = N2O_SyncPolicy_Save(&cjson_data); // 存储同步策略的各种参数
        if (err == 1)
        {
            Publish_Reply_Message(client, true, "sync");
        }
        else
        {
            Publish_Reply_Message(client, false, "sync");
        }
    }
}
// N2O警报报文解析
int N2OAlarm_jsondata(cJSON *rx_json, myCJson *data)
{
    mbedtls_md5_context md5_ctx;
    char wait_encrypt_str[255] = {0};
    unsigned char decrypt[16];
    char decrypt_cs[33];

    static const char *TAG = "Control_N2O_jsondata";
    if (rx_json == NULL || data == NULL)
    {
        return 0;
    }
    // ESP_LOGI(TAG, "%s", cJSON_Print(rx_json));

    if (cJSON_GetObjectItem(rx_json, "deviceType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceType Item!");

        return 0;
    }
    data->deviceType = cJSON_GetObjectItem(rx_json, "deviceType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "subType") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no subType Item!");

        return 0;
    }
    data->subType = cJSON_GetObjectItem(rx_json, "subType")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "deviceMAC") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no deviceMAC Item!");

        return 0;
    }
    data->deviceMAC = cJSON_GetObjectItem(rx_json, "deviceMAC")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "groupId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no groupId Item!");

        return 0;
    }
    data->groupId = cJSON_GetObjectItem(rx_json, "groupId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "familyId") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no familyId Item!");

        return 0;
    }
    data->familyId = cJSON_GetObjectItem(rx_json, "familyId")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "operate") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->operate = cJSON_GetObjectItem(rx_json, "operate")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "content") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    cJSON *content = cJSON_GetObjectItem(rx_json, "content");

    if (cJSON_GetObjectItem(content, "type") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no operate Item!");

        return 0;
    }
    data->type = cJSON_GetObjectItem(content, "type")->valuestring;
    cJSON *sub_content = cJSON_GetObjectItem(content, "content");
    cJSON *item = cJSON_GetArrayItem(sub_content, 0);
    if (cJSON_GetObjectItem(item, "alarmEn") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no alarmEn Item!");
        return 0;
    }
    else
    {
        data->sub_alarmEn = cJSON_GetObjectItem(item, "alarmEn")->valuestring;
    }

    if (cJSON_GetObjectItem(item, "alarmMaxValue") == NULL)
    {
        ESP_LOGE(TAG, "rx json have no alarmEn Item!");
        return 0;
    }
    else
    {
        data->sub_alarmMaxValue = cJSON_GetObjectItem(item, "alarmMaxValue")->valuestring;
    }

    if (cJSON_GetObjectItem(rx_json, "source") == NULL)
    {
        printf("rx json have no source Item!\n");

        return 0;
    }
    data->source = cJSON_GetObjectItem(rx_json, "source")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "version") == NULL)
    {
        printf("rx json have no version Item!\n");

        return 0;
    }
    data->version = cJSON_GetObjectItem(rx_json, "version")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "timestamp") == NULL)
    {
        printf("rx json have no timestamp Item!\n");

        return 0;
    }
    data->timestamp = cJSON_GetObjectItem(rx_json, "timestamp")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "sign") == NULL)
    {
        printf("rx json have no sign Item!\n");

        return 0;
    }
    data->sign = cJSON_GetObjectItem(rx_json, "sign")->valuestring;

    if (cJSON_GetObjectItem(rx_json, "append") == NULL)
    {
        printf("rx json have no sign Item!\n");
        data->append = "0\0";
    }
    else
    {
        data->append = cJSON_GetObjectItem(rx_json, "append")->valuestring;
    }

    // 记得把md5校验补了
    strcat(wait_encrypt_str, "Alive");
    strcat(wait_encrypt_str, data->source);
    strcat(wait_encrypt_str, data->timestamp);
    mbedtls_md5_init(&md5_ctx);
    mbedtls_md5_starts(&md5_ctx);
    mbedtls_md5_update(&md5_ctx, (unsigned char *)wait_encrypt_str, strlen((char *)wait_encrypt_str));
    mbedtls_md5_finish(&md5_ctx, decrypt);
    sprintf(decrypt_cs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", decrypt[0], decrypt[1], decrypt[2], decrypt[3], decrypt[4], decrypt[5], decrypt[6], decrypt[7], decrypt[8], decrypt[9],
            decrypt[10], decrypt[11], decrypt[12], decrypt[13], decrypt[14], decrypt[15]);
    mbedtls_md5_free(&md5_ctx);

    if (strcmp((char *)decrypt_cs, data->sign) == 0) // 校验正确
    {
        ESP_LOGI(TAG, "MD5 success!!!\n");
        return 1;
    }
    else
    {
        ESP_LOGI(TAG, "MD5 failed !!!\n");
    }
    return 0;
}

void Run_N2OAlarm_JsonData(esp_mqtt_client_handle_t *client)
{
    if (strcmp(cjson_data.type, "N2Oalarm") == 0)
    {
        // 存储相关指令
        nvs_handle_t my_handle;
        esp_err_t err = nvs_open(N2O_Storage, NVS_READWRITE, &my_handle);
        // 存储开关状态
        err = nvs_set_str(my_handle, "alarmEn", cjson_data.sub_alarmEn);
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "alarmEn set error!!!");
            return;
        }
        err = nvs_set_str(my_handle, "alarmMaxValue", cjson_data.sub_alarmMaxValue);
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "alarmMaxValue set error!!!");
            return;
        }
        err = nvs_commit(my_handle);
        if (err != ESP_OK)
        {
            ESP_LOGE(TAG, "nvs_commit error!!!");
            return;
        }
        nvs_close(my_handle);
    }
    // 依据报文开启或关闭报警任务
    int check = N2O_Alarm_TaskKEY();

    if (check == 1)
    {
        Publish_Reply_Message(client, true, "alarm");
    }
    else
    {
        Publish_Reply_Message(client, false, "alarm");
    }
}

// if (strcmp(cjson_data.sub_alarmEn, "enable") == 0)
// {
//     alarmMaxValue = cjson_data.sub_alarmMaxValue;
//     //创建报警任务
//     xTaskCreate(N2O_Alarm_Task, "N2O_Alarm_Task", 4096, NULL, 18, &N2OAlarmHandle);
//     //标志位置为1
// }

// int mqtt_led_control(const char *MAC, myCJson *data)
// {
//     printf("led_control_in\n");
//     if (strcmp(MAC, data->deviceMACvaluestring) == 0 &&
//         strcmp("control", data->operate->valuestring) == 0 &&
//         strcmp("led", data->type->valuestring) == 0)
//     {
//         if (strcmp("openBtn", data->sub_operate->valuestring) == 0)
//         {
//             led_statue(1);
//             printf("LED_ON\n");
//         }
//         else if (strcmp("closeBtn", data->sub_operate->valuestring) == 0)
//         {
//             led_statue(0);
//             printf("LED_OFF\n");
//         }
//     }
//     return 0;
// }